/**
 * 
 */
package com.jdy.haoduoaiteacher.view;

import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.Path.Direction;
import android.graphics.PointF;
import android.graphics.RectF;
import android.graphics.Region;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;

import com.jdy.haoduoai.intface.OnColorChangedListener;
import com.jdy.haoduoai.util.Tools;
import com.ycsj.goldmedalnewconcept.R;

/**
 * @author zp 2016-11-14 下午2:41:20
 */
public class ColorPickerView extends View {

  protected int WIDTH;

  protected int HEIGHT;

  private final Paint mPaint;

  private int strokeColor = Color.argb(255, 255, 255, 255);

  private final float strokeWidth = 16;

  private final float FIXED_RADIUS = 357;

  private float RADIUS_1 = FIXED_RADIUS;

  private float FIXED_BUTTON_RADIUS = 40;

  private float INIT_PICKER_ANGLE = 45;

  private float BUTTON_RADIUS = FIXED_BUTTON_RADIUS;

  private PointF REF_CENTER_POINT;

  private PointF CP_BUTTON_START_POINT;

  private ColorPickerButton mCPBtn;

  private Region mActiveRegion;

  private RectF mActiveRectF;

  private float ratio;

  private OnColorChangedListener mColorChangedListener;

  private final static String TAG = "ColorPickerView";

  /**
   * @param context
   * @param attrs
   * @param defStyleAttr
   */
  public ColorPickerView(Context context, AttributeSet attrs, int defStyleAttr) {
    super(context, attrs, defStyleAttr);
    // TODO Auto-generated constructor stub
    mPaint = new Paint();

    mPaint.setAntiAlias(true);

    mPaint.setStrokeWidth(strokeWidth);

    mPaint.setColor(strokeColor);

    mPaint.setStyle(Paint.Style.FILL_AND_STROKE);

    this.ratio = Tools.getPixelRatio(context);

    TypedArray typeArray = context.obtainStyledAttributes(attrs,
        R.styleable.ColorPickerViewxxb);

    strokeColor = typeArray.getColor(R.styleable.ColorPickerViewxxb_cpi_color,
        strokeColor);

    FIXED_BUTTON_RADIUS = typeArray.getFloat(
        R.styleable.ColorPickerViewxxb_cpi_radius, FIXED_BUTTON_RADIUS);

    INIT_PICKER_ANGLE = typeArray.getFloat(
        R.styleable.ColorPickerViewxxb_cpi_init_angle, INIT_PICKER_ANGLE);

    typeArray.recycle();

    if (isInEditMode())
      return;

  }

  /**
   * @param context
   * @param attrs
   */
  public ColorPickerView(Context context, AttributeSet attrs) {
    this(context, attrs, 0);
    // TODO Auto-generated constructor stub
  }

  /**
   * @param context
   */
  public ColorPickerView(Context context) {
    this(context, null);
    // TODO Auto-generated constructor stub
  }

  private void initParameters() {

    REF_CENTER_POINT = new PointF(WIDTH / 2, HEIGHT / 2);

    CP_BUTTON_START_POINT = getPointByAngle(REF_CENTER_POINT, RADIUS_1,
        Math.toRadians(INIT_PICKER_ANGLE));

    mActiveRectF = new RectF(REF_CENTER_POINT.x - RADIUS_1, REF_CENTER_POINT.y
        - RADIUS_1, REF_CENTER_POINT.x + RADIUS_1, REF_CENTER_POINT.y
        + RADIUS_1);

    Path circlePath = new Path();

    circlePath.addCircle(REF_CENTER_POINT.x, REF_CENTER_POINT.y, RADIUS_1,
        Direction.CW);

    mActiveRegion = new Region();

    mActiveRegion.setPath(circlePath, new Region((int) mActiveRectF.left,
        (int) mActiveRectF.top, (int) mActiveRectF.right,
        (int) mActiveRectF.bottom));

    mCPBtn = new ColorPickerButton(CP_BUTTON_START_POINT, BUTTON_RADIUS);
  }

  /**
   * angle is degree *not* radians
   * 
   * @param angle
   */
  public void setInitAngle(float angle) {
    if (angle < 0 || angle > 360)
      return;
    INIT_PICKER_ANGLE = angle;
    if (mCPBtn != null) {
      mCPBtn.updatePosition(angle);
    }
  }

  private PointF getPointByAngle(PointF center, float radius, double rotateAngle) {
    PointF p = new PointF();
    p.x = center.x + radius * (float) Math.cos(rotateAngle);
    p.y = center.y + radius * (float) Math.sin(rotateAngle);
    return p;
  }

  public void setColorPickerChangedListener(OnColorChangedListener listener) {
    this.mColorChangedListener = listener;
  }

  public PointF getStartPickerPositioin() {
    if (mCPBtn != null)
      return mCPBtn.Position;
    else
      return null;
  }

  private class ColorPickerButton {
    public PointF Position;

    public float Radius;

    private float adjustLength = 10;

    public ColorPickerButton(PointF pos, float r) {
      this.Position = pos;

      this.Radius = r;

      this.adjustLength = r;
    }

    public void updatePosition(float degree) {
      this.Position = getPointByAngle(REF_CENTER_POINT, RADIUS_1,
          Math.toRadians(degree));
    }

    public void setPosition(int x, int y) {
      // TODO Auto-generated method stub

      double tx = x - REF_CENTER_POINT.x, ty = y - REF_CENTER_POINT.y;

      double t_length = Math.sqrt(tx * tx + ty * ty);

      // double angle = Math.PI / 2 - Math.acos(ty / t_length);
      double angle = Math.PI
          + Math.atan2(REF_CENTER_POINT.y - y, REF_CENTER_POINT.x - x);

      this.Position.x = (float) (REF_CENTER_POINT.x + Math.cos(angle)
          * RADIUS_1);

      this.Position.y = (float) (REF_CENTER_POINT.y + Math.sin(angle)
          * RADIUS_1);

      if (mColorChangedListener != null) {
        mColorChangedListener.onColorPickerPositionChanged(this.Position.x,
            this.Position.y, Math.toDegrees(angle));
      }

    }

    public void draw(Canvas canvas) {
      canvas.drawCircle(Position.x, Position.y, Radius, mPaint);
    }

    /**
     * @param xTouch
     * @param yTouch
     * @return
     */
    public boolean contains(int x, int y) {
      // TODO Auto-generated method stub
      if (x >= this.Position.x - Radius - adjustLength
          && x <= this.Position.x + Radius + adjustLength
          && y >= this.Position.y - Radius - adjustLength
          && y <= this.Position.y + Radius + adjustLength) {

        return true;
      } else
        return false;
    }

  }

  @Override
  protected void onSizeChanged(int w, int h, int oldW, int oldH) {
    WIDTH = w;

    HEIGHT = h;

    initParameters();
    // mPaint.setShader(new RadialGradient(WIDTH / 2, HEIGHT / 2, WIDTH / 2,
    // Color.TRANSPARENT, Color.BLACK, TileMode.MIRROR));
  }

  @Override
  protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {

    int desiredWidth = (int) (1200 * this.ratio);

    int desiredHeight = (int) (1200 * this.ratio);

    RADIUS_1 = this.ratio * FIXED_RADIUS;

    BUTTON_RADIUS = this.ratio * FIXED_BUTTON_RADIUS;

    int widthMode = MeasureSpec.getMode(widthMeasureSpec);

    int widthSize = MeasureSpec.getSize(widthMeasureSpec);

    int heightMode = MeasureSpec.getMode(heightMeasureSpec);

    int heightSize = MeasureSpec.getSize(heightMeasureSpec);

    int width;

    int height;

    // Measure Width
    if (widthMode == MeasureSpec.EXACTLY) {
      // Must be this size
      width = widthSize;
    } else if (widthMode == MeasureSpec.AT_MOST) {
      // Can't be bigger than...
      width = Math.min(desiredWidth, widthSize);
    } else {
      // Be whatever you want
      width = desiredWidth;
    }

    // Measure Height
    if (heightMode == MeasureSpec.EXACTLY) {
      // Must be this size
      height = heightSize;
    } else if (heightMode == MeasureSpec.AT_MOST) {
      // Can't be bigger than...
      height = Math.min(desiredHeight, heightSize);
    } else {
      // Be whatever you want
      height = desiredHeight;
    }

    // MUST CALL THIS
    setMeasuredDimension(width, height);
  }

  @Override
  protected void onDraw(Canvas canvas) {

    mCPBtn.draw(canvas);

  }

  private boolean mSelected = false;

  int xTouch;

  int yTouch;

  @Override
  public boolean onTouchEvent(final MotionEvent event) {
    boolean handled = false;

    // get touch event coordinates and make transparent circle from it
    switch (event.getAction()) {
    case MotionEvent.ACTION_DOWN:

      xTouch = (int) event.getX(0);
      yTouch = (int) event.getY(0);

      this.mSelected = mCPBtn.contains(xTouch, yTouch);
      invalidate();
      handled = true;
      break;

    case MotionEvent.ACTION_MOVE:

      Log.w(TAG, "Move");
      // xTouch = (int) event.getX(0);
      // yTouch = (int) event.getY(0);

      if (this.mSelected) {
        this.mCPBtn.setPosition((int) event.getX(0), (int) event.getY(0));
      }
      invalidate();
      handled = true;
      break;

    case MotionEvent.ACTION_UP:
      Log.w(TAG, "Motion Up");
      xTouch = (int) event.getX(0);
      yTouch = (int) event.getY(0);
      // this.mOptionButton.setDiscretePosition(xTouch, yTouch,
      // mOptionAreaList);
      this.mSelected = false;
      invalidate();
      handled = true;
      break;

    case MotionEvent.ACTION_CANCEL:
      Log.w(TAG, "Motion Cancel");
      xTouch = (int) event.getX(0);
      yTouch = (int) event.getY(0);
      // this.mOptionButton.setDiscretePosition(xTouch, yTouch,
      // mOptionAreaList);
      this.mSelected = false;
      invalidate();
      handled = true;
      break;

    default:
      break;
    }

    handled = mActiveRegion.contains((int) event.getX(0), (int) event.getY(0));

    return super.onTouchEvent(event) || handled;
  }
}
